home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / umich / tex / undump.zoo / undump.c < prev    next >
C/C++ Source or Header  |  1989-09-21  |  5KB  |  222 lines

  1. /*
  2.  *  undump new old <args>
  3.  *    undump the memory image of old to new
  4.  *    old is run with args, and when it exits, its memory image is
  5.  *    undump'ed into new.
  6.  *    Gcc probably required.
  7.  *
  8.  *        ++jrb    bammi@dsrgsun.ces.cwru.edu
  9.  */
  10. #include <stdio.h>
  11. #include <basepage.h>
  12. #include <st-out.h>
  13. #include <osbind.h>
  14. #include <string.h>
  15.  
  16. #define BSIZ    8192L
  17. char buf[BSIZ];
  18. char oldname[FILENAME_MAX], newname[FILENAME_MAX];
  19.  
  20. static unsigned long getlong(FILE *f)
  21. {
  22.     unsigned long l;
  23.     if(fread(&l, sizeof l, 1, f) != 1)
  24.     {
  25.     fprintf(stderr,"%s: unexpected EOF\n", oldname);
  26.     exit(92);
  27.     }
  28.     return l;
  29. }
  30.  
  31. static void copy(FILE *, FILE *, unsigned long);
  32. static void makeenv(int, char **, char **);
  33.  
  34. int main(int argc, char **argv, char **envp)
  35. {
  36.     FILE *new, *old;
  37.     FILE *fopen();
  38.     struct aexec newhead, oldhead;
  39.     BASEPAGE *bp;
  40.     long l;
  41.     unsigned long roffset, ul;
  42.     char *patchloc;
  43.     unsigned long getlong(FILE *);
  44.     
  45.     /* chk args */
  46.     if(argc < 3)
  47.     {
  48.     fprintf(stderr,"usage: undump new old [args..]\n");
  49.     exit(1);
  50.     }
  51.  
  52.     /* open files */
  53.     if((new = fopen(argv[1], "wb")) == NULL)
  54.     {
  55.     perror(argv[1]);
  56.     exit(2);
  57.     }
  58.     strncpy(newname, argv[1], FILENAME_MAX);
  59.     if((old = fopen(argv[2], "rb")) == NULL)
  60.     {
  61.     perror(argv[2]);
  62.     exit(3);
  63.     }
  64.     strncpy(oldname, argv[2], FILENAME_MAX);
  65.  
  66.     /* read header from old */
  67.     if(fread(&oldhead, sizeof oldhead, 1, old) != 1)
  68.     {
  69.     perror(oldname);
  70.     exit(4);
  71.     }
  72.     if(A_BADMAG(oldhead))    /* check its magic # */
  73.     {
  74.     fprintf(stderr,"%s: bad magic number 0x%x\n", oldname,oldhead.a_magic);
  75.     exit(5);
  76.     }
  77.     /* make up new head */
  78.     newhead = oldhead;
  79.     newhead.a_data = oldhead.a_data + oldhead.a_bss;
  80.     newhead.a_bss  = 0L;
  81.     
  82.     /* write new head */
  83.     if(fwrite(&newhead, sizeof newhead, 1, new) != 1)
  84.     {
  85.     perror(newname);
  86.     exit(6);
  87.     }
  88.  
  89.     /* pick up args and make env */
  90.     makeenv(argc, argv, envp);
  91.     /* &buf[0] == command tail, &buf[130] == envp */
  92.  
  93.     /* load old into mem and grab basepage */
  94.     if((l = Pexec(PE_LOAD, oldname, buf, &buf[130])) < 0)
  95.     {
  96.     fprintf(stderr,"%s: could'nt load\n", oldname);
  97.     exit(7);
  98.     }
  99.     bp = (BASEPAGE *)l;
  100.     roffset = (unsigned long)(bp->p_tbase);    /* grab reloc offset */
  101.     bzero(bp->p_bbase, bp->p_blen);    /* not sure if this is needed */
  102.     
  103.     /* now do the just go */
  104.     (void)Pexec(PE_GO, 0L, bp, 0L);
  105.  
  106.     /* un-relocate stuff in the text and data segments in core,
  107.        and then dump it all into new */
  108.     /* seek to reloc part of old */
  109.     if(fseek(old, A_SYMOFF(oldhead) + oldhead.a_syms, SEEK_SET) < 0)
  110.     {
  111.     perror(oldname);
  112.     exit(8);
  113.     }
  114.  
  115.     /* step through relocs, reading relocs from old, and unrelocating */
  116.     /* the corresponding items in core */
  117.     ul = getlong(old); /* initial off from begining of text */
  118.     patchloc = (char *)(roffset + ul);
  119.     while(1)
  120.     {
  121.     *((unsigned long *)patchloc) -= roffset; /* un-reloc */
  122.       more:
  123.     if((ul = (unsigned long)getc(old)) == 0)
  124.         break;    /* all done */
  125.     if(ul == 1)
  126.     {
  127.         patchloc += 254L;
  128.         goto more;
  129.     }
  130.     else if(ul == 3)
  131.     {
  132.         fprintf(stderr,"WARNING: illegal reloc %ld (ignored)\n", ul);
  133.         goto more;
  134.     } /* note we let ul==2 pass thru */
  135.     patchloc += ul;
  136.     }
  137.  
  138.     /* dump text+data+bss from core into new */
  139.     if(fwrite(bp->p_tbase, newhead.a_text + newhead.a_data, 1, new) != 1)
  140.     {
  141.     perror(newname);
  142.     exit(11);
  143.     }
  144.     if(fseek(old, A_SYMOFF(oldhead), SEEK_SET) < 0)
  145.     {
  146.     perror(oldname);
  147.     exit(12);
  148.     }
  149.     
  150.     /* copy rest of old into new (ie. the symt if any and the reloc) */
  151.     copy(old, new, 0x7fffffffL);
  152.  
  153.     
  154.     fclose(new);
  155.     fclose(old);
  156.     return 0;
  157. }
  158.  
  159. /*
  160.  * copy from -> to upto count bytes or EOF
  161.  */
  162. static void copy(FILE *from, FILE *to, unsigned long count)
  163. {
  164.     register unsigned long n;
  165.     
  166.     while(count > 0)
  167.     {
  168.     n = (count > BSIZ) ? BSIZ : count;
  169.     if((n = fread(buf, 1, n, from)) <= 0)
  170.         return;
  171.     if(fwrite(buf, 1, n, to) != n)
  172.     {
  173.         perror(newname);
  174.         exit(13);
  175.     }
  176.     count -= n;
  177.     }
  178. }
  179.  
  180. extern char **environ;
  181.  
  182. static void makeenv(int argc, char **argv, char **envp)
  183. {
  184.     int i, count, l;
  185.     char *p;
  186.     
  187.     bzero(buf, 128L);
  188.     if(envp == NULL)
  189.     envp = environ;
  190.     p = &buf[130];
  191.     if(envp)
  192.     {
  193.     for(; *envp; envp++)
  194.     {
  195.         strcpy(p, *envp);
  196.         p += (strlen(*envp) + 1);
  197.     }
  198.     }
  199.     strcpy(p, "ARGV=");
  200.     p += (strlen(p) + 1);    
  201.     strcpy(p, argv[2]);
  202.     p += (strlen(p) + 1);
  203.     strcpy(buf, " ");
  204.     for(count = 0, i = 3; i < argc; i++)
  205.     {
  206.     l = strlen(argv[i]);
  207.     if( (count += l) < 127)
  208.     {
  209.         strcat(buf, argv[i]);
  210.         if((i+1) < argc)
  211.         {
  212.         strcat(buf, " ");
  213.         count++;
  214.         }
  215.     }
  216.     strcpy(p, argv[i]);
  217.     p += (l+1);
  218.     }
  219.     *p++ = '\0'; *p = '\0';
  220.     buf[0] = strlen(&buf[1]);
  221. }
  222.